package com.ac.scum.log.web.model.user.service;

import com.ac.common.core.exception.BaseException;
import com.ac.common.core.exception.config.ExceptionType;
import com.ac.scum.log.bean.AdminUser;
import com.ac.scum.log.bean.UserPreference;
import com.ac.scum.log.web.dto.SendPhoneCodeSmsDTO;
import com.ac.scum.log.web.dto.login.LoginDTO;
import com.ac.scum.log.web.model.login.service.EncodingSalt;
import com.ac.scum.log.web.model.login.service.LoginService;
import com.ac.scum.log.web.model.sms.SMSService;
import com.ac.scum.log.web.model.user.mapper.AdminUserMapper;
import com.ac.scum.log.web.model.user.mapper.UserPreferenceMapper;
import com.ac.scum.log.web.utils.user.CurrentUserUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.micrometer.common.util.StringUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@AllArgsConstructor
public class UserService extends ServiceImpl<AdminUserMapper, AdminUser> {
    private final SMSService smsService;
    private final EncodingSalt encodingSalt;
    private final LoginService loginService;
    private final AdminUserMapper adminUserMapper;
    private final UserPreferenceMapper userPreferenceMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    public Boolean sendSMS(String phone) {
        String code = String.valueOf((int) (Math.random() * 10000));
        smsService.sendUniSMS(SendPhoneCodeSmsDTO.builder().code(code).phone(phone).data(Map.of("code", code, "ttl", "5")).templateCode("pub_verif_register_ttl").signName("SCUM日志").build());
        redisTemplate.opsForValue().set("REG-CODE::" + phone, code, 7, TimeUnit.MINUTES);
        log.info("发送一条验证码短信{}，{}", phone, code);
        return Boolean.TRUE;
    }

    @Transactional
    public LoginDTO register(String phone, String code) throws BaseException {
        String codeForRedis = (String) redisTemplate.opsForValue().get("REG-CODE::" + phone);
        if (StringUtils.isNotBlank(codeForRedis)) {
            if (code.equals(codeForRedis)) {
                AdminUser adminUser = adminUserMapper.findUserByPhone(phone);
                if (adminUser != null) {
                    return loginService.login(adminUser, Boolean.FALSE);
                }
                adminUser = new AdminUser();
                adminUser.setSalt("00000000");
                adminUser.setPassword("91c35a779eae2b598780720c24a09609");
                adminUser.setUsername(phone);
                adminUser.setPhone(phone);
                adminUserMapper.insert(adminUser);
                Long userId = adminUser.getId();
                userPreferenceMapper.insert(new UserPreference() {{
                    setUserId(userId);
                }});
                return loginService.login(adminUser, Boolean.FALSE);
            }
        }
        throw new BaseException(ExceptionType.Code_Mismatch);
    }


    public Boolean changePassword(String newPassword, String oldPassword) throws BaseException {

        AdminUser user = adminUserMapper.findUserByPhone(CurrentUserUtil.getCurrentLoginUserPhone());

        if (!loginService.isInitPassword(CurrentUserUtil.getCurrentLoginUserPhone()) && !encodingSalt.encoding(oldPassword, user.getSalt()).getAfter().equals(user.getPassword())) {
            throw new BaseException(ExceptionType.Password_Error);
        }
        EncodingSalt.EncodingBean encoding = encodingSalt.encoding(newPassword);
        user.setSalt(encoding.getSalt());
        user.setPassword(encoding.getAfter());
        adminUserMapper.updateById(user);
        loginService.logout();
        return Boolean.TRUE;
    }
}
